/**
	This file is part of MemoryTrace.

	MemoryTrace is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

        Contributed by Ameziane NAIT ABDELAZIZ.
        
	MemoryTrace is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with MemoryTrace.  If not, see <http://www.gnu.org/licenses/>.
**/


/*! \file SharedMemory.h
  \brief Une classe template qui permet de construire des segments de mémoire partagées.
*/

#ifndef SHAREDMEMORY_H
#define	SHAREDMEMORY_H

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string>
#include <cassert>

#include <cstdlib>
#include <sys/msg.h>
#include <stddef.h>

#include "alloc_event_t.h"

/*---------------------------SHARED MEMORY FUNCTIONS-------------------------*/

#define MODE  (int)'R'

/**
 * \class SharedMemory
 * \brief Cette classe permet creer des segment de memoire partagee
 */
template <size_t shmemSize,const enum_keys key_ > 
  class SharedMemory{ 
 private:
  static key_t key;
  static int shmId;
  static char* data;
  
 public:
  /**
   * \brief Construit une clef pour partager la mémoire
   */
  static  void makeKey();
  /**
   * \brief Connect le processus appelant au segment partagé
   */
  static  void connectToSegment();
  
  /**
   * \brief renvoie un pointeur vers la zone mémoire partagée
   */
  static  char* getPointerToShmem();
  
  /**
   * \brief détache le processus appelant du segment de mémoire partagée
   */
  static  void detachSegment();
  
  /**
   * \brief le processus appelant détruit le segment de memoire partagée
   */
  static void  destroyShmem();
};


template <size_t shmemSize,const enum_keys key_> char* SharedMemory<shmemSize,key_>::data ;
template <size_t shmemSize,const enum_keys key_> key_t SharedMemory<shmemSize,key_>::key;
template <size_t shmemSize,const enum_keys key_> int   SharedMemory<shmemSize,key_>::shmId ;



template <size_t shmemSize,const enum_keys key_> void SharedMemory<shmemSize,key_>::makeKey(){
  //const char *file =getenv(ipc_keys[key_]);
  //#ifdef DEBUG
  printf("IPC_KEYS: %s\n",ipc_keys[key_]);
  //#endif
  if((key=ftok(ipc_keys[key_],MODE)) == -1){
    perror("ftok");
    exit(1);
  }
}

template <size_t shmemSize,const enum_keys key_> void SharedMemory<shmemSize,key_>::connectToSegment(){
  
  
  printf("Construction d'un segment memoire de taille : %lu\n",shmemSize);
  if((shmId= shmget(key,shmemSize,0644 | IPC_CREAT)) == -1){
    //printf("Veuillez fixer correctement la variable d'environnement IPC_KEYS !!\n");
    perror("shmget");
    exit(1);
  }
}

template <size_t shmemSize,const enum_keys key_> char* SharedMemory<shmemSize,key_>::getPointerToShmem(){
  printf("shmID=%d\n",shmId);
  data=(char*)shmat(shmId,NULL,0);    
  return data;
}


template <size_t shmemSize,const enum_keys key_> void SharedMemory<shmemSize,key_>::detachSegment(){
  if(shmdt(data) == -1){
    perror("shmdt");
    exit(1);
  }
}

template <size_t shmemSize,const enum_keys key_> void SharedMemory<shmemSize,key_>::destroyShmem(){
  if(shmctl(shmId,IPC_RMID,NULL)==-1){
    perror("shmdt");
    exit(1);
  }
}

#endif	/* SHAREDMEMORY_H */

